<html>
<!-- TODO: Need to make the ouptut window go to the bottom on new output. 
Needs the line order changed. It's the same as trace2's
-->
<head>
<link rel="stylesheet" href="inventbook.css" type="text/css" media="all" />
<style type="text/css">
.highlight {
	background-color: #DDDDFF;
}

body {
	font-family: sans-serif;
}

h1 {
	text-align: center;
}

p {
	text-indent: 1em;
}

table { 
    border-style: solid; 
    border-width: 1px;
    border-collapse: collapse; 
} 

td { 
    border-style: solid; 
    border-width: 1px; 
    padding: 4px; 
}

ol {
	font-family: courier;
}
</style>
<script type="text/javascript">

function onBodyLoad()
{
	var currentStep = 1;
	changeToStep(currentStep);
}

function insertHighlight(sourceCode, x)
{
	return sourceCode.substring(0, x) + ' class="highlight"' + sourceCode.substring(x, sourceCode.length);
}

function getLinesToColsMap(sourceCode)
{
	var arrOfIndexes = new Array();
	arrOfIndexes[0] = 0; // Compensates for one-off error. This way step 1 is at arrOfIndexes[1].

	ind = 0;
	while (ind > -1)
	{
		ind = sourceCode.indexOf("<li>");
		if (ind > -1)
		{
			arrOfIndexes.push(ind + 3);
		}
		sourceCode = sourceCode.replace("<li>","XXXX");
	}
	return arrOfIndexes;
}

// TODO: Need to handle error conditions for these "DisplayType" functions that can handle bad keys.

function highlightedDisplayType(displayData, stepNum)
{
	// highlightData is an associate array with keys 'sourceCode' (a string), 'mapLinesToCols' (an array), 'linesExecutionOrder' (an associative array) 
	return insertHighlight(displayData['sourceCode'], displayData['mapLinesToCols'][displayData['linesExecutionOrder'][stepNum]]);
}

function mostRecentKeyDisplayType(displayData, stepNum)
{
	stepToUse = stepNum;
	while (displayData[stepToUse] == undefined)
	{
		stepToUse -= 1;
		if (stepToUse <= 0) return "";
	}
	return displayData[stepToUse];
}

function cumulativeDisplayType(displayData, stepNum)
{
	var retVal = '';
	for (i = 0 ; i <= stepNum ; i++)
	{
		if (displayData[i] != undefined)
		{
			retVal += displayData[i];
		}
	}
	return retVal;
}

function oneToOneDisplayType(displayData, stepNum)
{
	if (displayData[stepNum] == undefined)
	{
		return '';
	}
	else
	{
		return displayData[stepNum];
	}
}

function assocArraySize(assocArr)
{
	var counter = 0;
	for (var i in assocArr)
	{
	counter++;
	}
	return counter;
}

var sourceCodeData = new Array();
// This is a single string that contains an HTML Ordered List, with each line of source code in an <li/> tag.
sourceCodeData['sourceCode'] = "<ol start=1>\n<li>import random<\/li>\n<li><\/li>\n<li>HANGMANPICS = [\'\'\'<\/li>\n<li><\/li>\n<li>    +------+<\/li>\n<li>    |      |<\/li>\n<li>    |      |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>==============\'\'\', \'\'\'<\/li>\n<li><\/li>\n<li>    +------+<\/li>\n<li>    |      |<\/li>\n<li>    |      |<\/li>\n<li>    O      |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>==============\'\'\', \'\'\'<\/li>\n<li><\/li>\n<li>    +------+<\/li>\n<li>    |      |<\/li>\n<li>    |      |<\/li>\n<li>    O      |<\/li>\n<li>    |      |<\/li>\n<li>    |      |<\/li>\n<li>    |      |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>==============\'\'\', \'\'\'<\/li>\n<li><\/li>\n<li><\/li>\n<li>    +------+<\/li>\n<li>    |      |<\/li>\n<li>    |      |<\/li>\n<li>    O      |<\/li>\n<li>   \/|      |<\/li>\n<li>  \/ |      |<\/li>\n<li>    |      |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>==============\'\'\', \'\'\'<\/li>\n<li><\/li>\n<li><\/li>\n<li>    +------+<\/li>\n<li>    |      |<\/li>\n<li>    |      |<\/li>\n<li>    O      |<\/li>\n<li>   \/|\\     |<\/li>\n<li>  \/ | \\    |<\/li>\n<li>    |      |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>==============\'\'\', \'\'\'<\/li>\n<li><\/li>\n<li><\/li>\n<li>    +------+<\/li>\n<li>    |      |<\/li>\n<li>    |      |<\/li>\n<li>    O      |<\/li>\n<li>   \/|\\     |<\/li>\n<li>  \/ | \\    |<\/li>\n<li>    |      |<\/li>\n<li>   \/       |<\/li>\n<li>  \/        |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>==============\'\'\', \'\'\'<\/li>\n<li><\/li>\n<li><\/li>\n<li>    +------+<\/li>\n<li>    |      |<\/li>\n<li>    |      |<\/li>\n<li>    O      |<\/li>\n<li>   \/|\\     |<\/li>\n<li>  \/ | \\    |<\/li>\n<li>    |      |<\/li>\n<li>   \/ \\     |<\/li>\n<li>  \/   \\    |<\/li>\n<li>           |<\/li>\n<li>           |<\/li>\n<li>==============\'\'\']<\/li>\n<li><\/li>\n<li>words = \'ant baboon badger bat bear beaver beetle bird camel cat clam cobra cougar coyote crab crane crow deer dog donkey duck eagle ferret fish fox frog goat goose hawk iguana jackal koala leech lemur lion lizard llama mite mole monkey moose moth mouse mule newt otter owl oyster panda parrot pigeon python quail rabbit ram rat raven rhino salmon seal shark sheep skunk sloth slug snail snake spider squid stork swan tick tiger toad trout turkey turtle wasp weasel whale wolf wombat worm yak zebra\'.split()<\/li>\n<li><\/li>\n<li>def getRandomWord(wordList):<\/li>\n<li>    # This function returns a random string from the passed list of strings.<\/li>\n<li>    wordIndex = random.randint(0, len(wordList) - 1)<\/li>\n<li>    return wordList[wordIndex]<\/li>\n<li><\/li>\n<li>def displayBoard(HANGMANPICS, missedLetters, correctLetters, secretWord):<\/li>\n<li>    print HANGMANPICS[len(missedLetters)]<\/li>\n<li>    print<\/li>\n<li><\/li>\n<li>    print \'Missed letters:\',<\/li>\n<li>    for letter in missedLetters:<\/li>\n<li>        print letter,<\/li>\n<li>    print<\/li>\n<li><\/li>\n<li>    blanks = \'_\' * len(secretWord)<\/li>\n<li><\/li>\n<li>    for i in range(len(secretWord)): # replace blanks with correctly guessed letters<\/li>\n<li>        if secretWord[i] in correctLetters:<\/li>\n<li>            blanks = blanks[:i] + secretWord[i] + blanks[i+1:]<\/li>\n<li><\/li>\n<li>    for letter in blanks: # show the secret word with spaces in between each letter<\/li>\n<li>        print letter,<\/li>\n<li>    print<\/li>\n<li><\/li>\n<li>def getGuess(alreadyGuessed):<\/li>\n<li>    # Returns the letter the player entered. This function makes sure the player entered a single letter, and not something else.<\/li>\n<li>    while True:<\/li>\n<li>        print \'Guess a letter.\'<\/li>\n<li>        guess = raw_input()<\/li>\n<li>        guess = guess.lower()<\/li>\n<li>        if len(guess) != 1:<\/li>\n<li>            print \'Please enter a single letter.\'<\/li>\n<li>        elif guess in alreadyGuessed:<\/li>\n<li>            print \'You have already guessed that letter. Choose again.\'<\/li>\n<li>        elif guess not in \'abcdefghijklmnopqrstuvwxyz\':<\/li>\n<li>            print \'Please enter a LETTER.\'<\/li>\n<li>        else:<\/li>\n<li>            return guess<\/li>\n<li><\/li>\n<li>def playAgain():<\/li>\n<li>    # This function returns True if the player wants to play again, otherwise it returns False.<\/li>\n<li>    print \'Do you want to play again? (yes or no)\'<\/li>\n<li>    return raw_input().lower().startswith(\'y\')<\/li>\n<li><\/li>\n<li><\/li>\n<li>print \'H A N G M A N\'<\/li>\n<li>missedLetters = \'\'<\/li>\n<li>correctLetters = \'\'<\/li>\n<li>secretWord = getRandomWord(words)<\/li>\n<li>gameIsDone = False<\/li>\n<li><\/li>\n<li>while True:<\/li>\n<li>    displayBoard(HANGMANPICS, missedLetters, correctLetters, secretWord)<\/li>\n<li><\/li>\n<li>    # Let the player type in a letter.<\/li>\n<li>    guess = getGuess(missedLetters + correctLetters)<\/li>\n<li><\/li>\n<li>    if guess in secretWord:<\/li>\n<li>        correctLetters = correctLetters + guess<\/li>\n<li><\/li>\n<li>        # Check if the player has won<\/li>\n<li>        foundAllLetters = True<\/li>\n<li>        for i in range(len(secretWord)):<\/li>\n<li>            if secretWord[i] not in correctLetters:<\/li>\n<li>                foundAllLetters = False<\/li>\n<li>                break<\/li>\n<li>        if foundAllLetters:<\/li>\n<li>            print \'You have won!\'<\/li>\n<li>            gameIsDone = True<\/li>\n<li>    else:<\/li>\n<li>        missedLetters = missedLetters + guess<\/li>\n<li><\/li>\n<li>        # Check if player has guessed too many times and lost<\/li>\n<li>        if len(missedLetters) == len(HANGMANPICS) - 1:<\/li>\n<li>            displayBoard(HANGMANPICS, missedLetters, correctLetters, secretWord)<\/li>\n<li>            print \'You have run out of guesses!\\nAfter \' + str(len(missedLetters)) + \' missed guesses and \' + str(len(correctLetters)) + \' correct guesses, the word was \"\' + secretWord + \'\"\'<\/li>\n<li>            gameIsDone = True<\/li>\n<li><\/li>\n<li>    # Ask the player if they want to play again (but only if the game is done).<\/li>\n<li>    if gameIsDone:<\/li>\n<li>        if playAgain():<\/li>\n<li>            missedLetters = \'\'<\/li>\n<li>            correctLetters = \'\'<\/li>\n<li>            gameIsDone = False<\/li>\n<li>            secretWord = getRandomWord(words)<\/li>\n<li>        else:<\/li>\n<li>            break<\/li><\/ol>\n";
// mapLinesToCols gives the indexes inside sourceCodeData['sourceCode'] that each <li/> tag begins. This index is used to dynamically add HTML to make the <li/> tag highlighted. e.g. mapLinesToCols[4] is the index of <li/> for the fourth line of code. (mapLinesToCols[0] is just padded with 0).
sourceCodeData['mapLinesToCols'] = getLinesToColsMap(sourceCodeData['sourceCode']);
// linesExecutionOrder has keys for steps and values of source code line numbers. These are fed to mapLinesToCols to get the position in the sourceCodeData['sourceCode'] string to insert the HTML highlight string. Note the difference: The 4th line of code is not necessarily the 4th line of code executed in a program (blank lines or loops will through this off). This could have been an array instead of an associative array, but using the incrementing keys makes it easier to edit.
sourceCodeData['linesExecutionOrder'] = {1:1, 2:2, 3:4, 4:6, 5:7, 6:9, 7:10, 8:12, 9:13, 10:14, 11:15, 12:17, 13:19, 14:20, 15:22, 16:25, 17:12, 18:13, 19:14, 20:15, 21:17, 22:19, 23:20, 24:22, 25:25, 26:12, 27:13, 28:14, 29:15, 30:17, 31:19, 32:20, 33:22, 34:25, 35:12, 36:13, 37:14, 38:15, 39:17, 40:19, 41:20, 42:22, 43:25, 44:12, 45:13,46:14, 47:15, 48:17, 49:19, 50:22, 51:23, 52:25, 53:12, 54:13, 55:14, 56:15, 57:17, 58:19, 59:22, 60:23, 61:25, 62:12, 63:28, 64:32, 65:33, 66:34, 67:35}; 

var currentStep = 1;
var MAXSTEP = assocArraySize(sourceCodeData['linesExecutionOrder']);


var variablesData = {1:"",
						4:"guessesTaken == 0",
						6:"guessesTaken == 0<br/>myName == 'Albert'",
						7:"guessesTaken == 0<br/>myName == 'Albert'<br/>number == 16",
						11:"guessesTaken == 0<br/>myName == 'Albert'<br/>number == 8<br/>guess == '12'",
						12:"guessesTaken == 0<br/>myName == 'Albert'<br/>number == 8<br/>guess == 12",
						13:"guessesTaken == 1<br/>myName == 'Albert'<br/>number == 8<br/>guess == 12",
						20:"guessesTaken == 1<br/>myName == 'Albert'<br/>number == 8<br/>guess == '6'",
						21:"guessesTaken == 1<br/>myName == 'Albert'<br/>number == 8<br/>guess == 6",
						22:"guessesTaken == 2<br/>myName == 'Albert'<br/>number == 8<br/>guess == 6",
						29:"guessesTaken == 2<br/>myName == 'Albert'<br/>number == 8<br/>guess == '8'",
						30:"guessesTaken == 2<br/>myName == 'Albert'<br/>number == 8<br/>guess == 8",
						31:"guessesTaken == 3<br/>myName == 'Albert'<br/>number == 8<br/>guess == 8",
						38:"guessesTaken == '3'<br/>myName == 'Albert'<br/>number == 8<br/>guess == 8"
						};

// notesData is the "one-to-one" display type. On step N, the N value will be in the window. If there is no N value, the window is blank.
var notesData = {1:"This is a comment, which the Python interpreter ignores.",
					2:"This line imports the <span class='m'>random<\/span> module so we can use the <span class='m'>randint()<\/span> function in our program.",
					3:"<span class='m'>guessesTaken<\/span> will indicate how many guesses the player has made.",
					4:"",
					5:"The <span class='m'>raw_input()<\/span> function call lets the player type in a string, and will store the string in the <span class='m'>myName<\/span> variable. Let's pretend the user typed in Albert.",
					6:"This function call will return a random integer that is stored in the <span class='m'>number<\/span> variable. Let's say the random integer was <span class='m'>8<\/span>.",
					7:"",
					8:"We check if the <span class='m'>while<\/span> statement's condition evaluates to <span class='m'>True<\/span>",
					9:"",
					10:"The player types in their guess. Let's say the player types in 12.",
					11:"We change <span class='m'>guess<\/span> to the integer version of it's value.",
					12:"",
					13:"The condition <span class='m'>guess < number<\/span> evaluates to <span class='m'>False<\/span>.",
					14:"The condition <span class='m'>guess > number<\/span> evaluates to <span class='m'>True<\/span>.",
					15:"",
					16:"The condition <span class='m'>guess == number<\/span> evaluates to <span class='m'>False<\/span>.",
					17:"The <span class='m'>while<\/span> statement's condition evaluates to <span class='m'>True<\/span> again.",
					18:"",
					19:"Let's say the player entered 6.",
					20:"",
					21:"",
					22:"The condition <span class='m'>guess < number<\/span> is <span class='m'>True<\/span>.",
					23:"",
					24:"The condition <span class='m'>guess > number<\/span> is <span class='m'>False<\/span>.",
					25:"The condition <span class='m'>guess == number<\/span> is <span class='m'>False<\/span>.",
					26:"The <span class='m'>while<\/span> statement's condition evaluates to <span class='m'>True<\/span> again.",
					27:"",
					28:"Let's say the player entered 8.",
					29:"",
					30:"",
					31:"The condition <span class='m'>guess < number<\/span> is <span class='m'>False<\/span>.",
					32:"The condition <span class='m'>guess > number<\/span> is <span class='m'>False<\/span>.",
					33:"The condition <span class='m'>guess == number<\/span> is <span class='m'>True<\/span>.",
					34:"The <span class='m'>break</span> statement causes the program execution to immediately leave the while loop.",
					35:"The condition <span class='m'>guess == number<\/span> is <span class='m'>True<\/span>.",
					38:"The condition <span class='m'>guess != number<\/span> is <span class='m'>False<\/span>.",
					39:"There are no more lines left in the program, so the program terminates."
					};

// outputData is of the "cumulative" type. The window will contain all of the text up to the index of the step number. e.g. If you are on step 7, the window will contain the strings in 0, 5, and 6.
var outputData = {5:"Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>Hello! What is your name?<br/>",
					6:"<font color='000000'>Albert</font><br/>",
					8:"Well, Albert, I am thinking of a number between 1 and 20.<br/>",
					10:"Take a guess.<br/>",
					11:"<font color='000000'>12</font><br/>",
					15:"Your guess is too high.<br/>",
					19:"Take a guess.<br/>",
					20:"<font color='000000'>6</font><br/>",
					24:"Your guess is too low.<br/>",
					28:"Take a guess.<br/>",
					29:"<font color='000000'>8</font><br/>",
					38:"Hooray, Albert! You guessed my number in 3 guesses!<br/>"
					};

function set(viewport, displayString)
{
	document.getElementById(viewport).innerHTML = displayString;
}

function changeToStep(stepNum)
{
	set('codeVP', highlightedDisplayType(sourceCodeData, stepNum)); // "highlighted code" display type	
	set('variablesVP', mostRecentKeyDisplayType(variablesData, stepNum)); // "most recent key" display type
	set('notesVP', oneToOneDisplayType(notesData, stepNum)); // "one-to-one" display type
	set('outputVP', cumulativeDisplayType(outputData, stepNum)); // "cumulative" display type
	document.getElementById('stepNumDisplay').innerHTML = stepNum;
}

function next()
{
	if (currentStep == MAXSTEP) return;
	currentStep += 1;
	changeToStep(currentStep);
}

function previous()
{
	if (currentStep == 1) return;
	currentStep -= 1;
	changeToStep(currentStep);
}

function jump(stepNum)
{
	stepNum = parseInt(stepNum, 10);
	if (stepNum < 1) return;
	if (stepNum > MAXSTEP) return;
	currentStep = stepNum;
	changeToStep(currentStep);
}

//===BEGIN FLOATING MENU CODE==============================================================================
<!--
floatX=10;
floatY=10;

// This script is copyright (c) Henrik Petersen, NetKontoret
// Feel free to use this script on your own pages as long as you do not change it.
// It is illegal to distribute the script as part of a tutorial / script archive.
// Updated version available at: http://www.echoecho.com/toolfloatinglayer.htm
// This comment and the 4 lines above may not be removed from the code.

NS6=false;
IE4=(document.all);
if (!IE4) {NS6=(document.getElementById);}
NS4=(document.layers);

function adjust() 
{
	if ((NS4) || (NS6)) 
	{
		lastX=window.pageXOffset + floatX;
		lastY=window.pageYOffset + floatY;
		
		if (NS4)
		{
			document.layers['floatlayer'].pageX = lastX;
			document.layers['floatlayer'].pageY = lastY;
		}
		if (NS6)
		{
			document.getElementById('floatlayer').style.left=lastX;
			document.getElementById('floatlayer').style.top=lastY;
		}
	}
	else if (IE4)
	{
		lastX=document.body.scrollLeft + floatX;
		lastY=document.body.scrollTop + floatY;
		document.all['floatlayer'].style.posLeft = lastX;
		document.all['floatlayer'].style.posTop = lastY;
	}
	setTimeout('adjust()',50);
}

function define()
{
	if ((NS4) || (NS6))
	{
		floatX=ifloatX;
		floatY=ifloatY;
	}
	if (IE4)
	{
		floatX=ifloatX;
		floatY=ifloatY;
	}
}
//===END FLOATING CODE==============================================================================
//-->

</script>

</head>
<body onLoad="onBodyLoad()">


<div style="position:relative; width:100%; height:100%;">
	<div style="position:absolute; width:50%; left:0px;"><br/><h1>Source code:guess.py</h1><span id='codeVP'></span></div>

<script>
if (NS4) {document.write('<LAYER NAME="floatlayer" LEFT="'+floatX+'" TOP="'+floatY+'">');}
if ((IE4) || (NS6)) {document.write('<div id="floatlayer" style="background-color:CCCCCC; padding:6px; position:absolute; left:'+floatX+'; top:'+floatY+';">');}
</script>
	<span style='background-color:CCCCCC;'><center><input type='button' value='Previous' onClick='previous()'>
	<input type='button' value='Next' onClick='next()'>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type='text' id='jumpTextfield' size='3' value='1'> <input type='button' value='Jump' onClick='jump(document.getElementById("jumpTextfield").value);'>
	&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Step #<span id="stepNumDisplay"></span></center></span>
<script>
if (NS4)
{
	document.write('</LAYER>');
}
if ((IE4) || (NS6))
{
	document.write('</DIV>');
}
ifloatX=floatX;
ifloatY=floatY;
define();
window.onresize=define;
lastX=-1;
lastY=-1;
adjust();
</script>

	<div id='variablesPane' style="position:absolute; right:0px; width:50%; ">
	<table border='0' width="100%">
	<tr><td>
	<h1>Current variable values</h1><span id='variablesVP'></span>
	</td></tr>

	<tr><td style="background-color:EEEEEE;">
	<h1>Notes</h1><span id='notesVP'></span>
	</td></tr>

	<tr><td>
	<div style='height:400; overflow:auto;'><h1>Program output</h1><span id='outputVP' style='color:0000FF;'></span></div>
	</td></tr>
	</table>
</div>


</body>
</html>